using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UIElements;

namespace DA.AnimGraph.Editor {
    public class ListViewAGE : VisualElement {

        private IList _itemsSource;
        public List<VisualElement> itemsUI { get; private set; }
        List<WrapperBase> wrapperUI;

        FoldoutPro foldout;
        ShoulderWidget shoulderWidget;
        VisualElement itemContainer;

        bool _enableCountController;
        public bool enableCountController {
            get => _enableCountController;
            set => EnableCountController(value);
        }

        public Action addButtonClicked { set; private get; }

        private Action<VisualElement, WrapperBase, int> _bindItem; // element, wrapper, index
        public Action<VisualElement, WrapperBase, int> bindItem {
            get { return _bindItem; }
            set {
                if (value != _bindItem) {
                    _bindItem = value;
                    Rebuild();
                }
            }
        }

        public string title {
            get => foldout?.text;
            set {
                if (foldout != null) {
                    foldout.text = value;
                }
            }
        }

        private Func<(VisualElement, WrapperBase)> _makeItem; // element, wrapper
        public Func<(VisualElement, WrapperBase)> makeItem {
            get {
                return _makeItem;
            }
            set {
                if (value != _makeItem) {
                    _makeItem = value;
                    Rebuild();
                }
            }
        }


        public IList itemsSource {
            get { return _itemsSource; }
            set {
                _itemsSource = value;
                Rebuild();
            }
        }

        public ListViewAGE(bool useFouldout = true) {
            style.borderRightWidth = 0;
            style.borderLeftWidth = 0;
            itemContainer = new VisualElement() {
                name = "item-container",
            };

            if (useFouldout) {
                foldout = new FoldoutPro();
                Add(foldout);

                foldout.Add(itemContainer);

                shoulderWidget = new ShoulderWidget();
                shoulderWidget.addButtonClicked += AddButtonClicked;
                foldout.AddToShoulder(shoulderWidget);
            } else {
                Add(itemContainer);
            }
        }

        void EnableCountController(bool enable) {
            if (shoulderWidget != null)
                shoulderWidget.style.display = enable ? DisplayStyle.Flex : DisplayStyle.None;
        }

        void AddButtonClicked() {
            addButtonClicked?.Invoke();
        }

        public void Rebuild() {
            if (itemsSource == null) return;
            if (makeItem == null) return;
            if (bindItem == null) return;

            if (itemsUI == null) {
                var count = itemsSource.Count;
                itemsUI = new(count);
                wrapperUI = new(count);
            }

            var dataCount = itemsSource.Count;
            var uiCount = itemsUI.Count;
            if (dataCount > uiCount) {
                for (int i = 0; i < dataCount - uiCount; i++) {
                    var (newEle, newWrapper) = makeItem();
                    itemsUI.Add(newEle);
                    wrapperUI.Add(newWrapper);
                }
            } else if (uiCount > dataCount) {
                for (int i = uiCount - 1; i >= dataCount; i--) {
                    itemsUI.RemoveAt(i);
                    wrapperUI.RemoveAt(i);
                }
            }

            itemContainer.Clear();
            for (int i = 0; i < itemsUI.Count; i++) {
                bindItem(itemsUI[i], wrapperUI[i], i);
                wrapperUI[i].Add(itemsUI[i]);
                itemContainer.Add(wrapperUI[i]);
            }
            if (shoulderWidget != null) {
                shoulderWidget.countDisplay = itemsUI.Count;
            }
        }

        // ======================

        public class ShoulderWidget : VisualElement {
            TextField shoulderDisplay;
            InlineButton addButton;

            public ShoulderWidget() {
                style.flexDirection = FlexDirection.RowReverse;

                shoulderDisplay = new TextField() {
                    isReadOnly = true,
                    style = {
                        minWidth = 40,
                    }
                };
                var textElement = shoulderDisplay.Q<TextElement>();
                textElement.style.marginLeft = 0;

                addButton = new InlineButton("+");

                Add(addButton);
                Add(shoulderDisplay);
            }

            public event Action addButtonClicked {
                add => addButton.clicked += value;
                remove => addButton.clicked -= value;
            }

            public int countDisplay {
                set => shoulderDisplay.value = value.ToString();
            }
        }
    }

    public class WrapperBase : VisualElement {
        public int index;

        protected InlineButton upButton;
        protected InlineButton downButton;
        protected InlineButton deleteButton;

        public event Action<int> upButtonClicked;
        public event Action<int> downButtonClicked;
        public event Action<int> deleteButtonClicked;
        protected virtual void BuildUI() {
            upButton = new InlineButton("↑");
            upButton.clicked += () => upButtonClicked(index);
            downButton = new InlineButton("↓");
            downButton.clicked += () => downButtonClicked(index);
            deleteButton = new InlineButton("X");
            deleteButton.clicked += () => deleteButtonClicked(index);

            upButton.style.display = DisplayStyle.None;
            downButton.style.display = DisplayStyle.None;
            deleteButton.style.display = DisplayStyle.None;

            _enableUp = false;
            _enableDown = false;
            _enableDelete = false;
        }

        bool _enableUp;
        public bool enableUp {
            get => _enableUp;
            set {
                if (_enableUp == value) return;
                _enableUp = value;

                if (value) {
                    upButton.style.display = DisplayStyle.Flex;
                } else {
                    upButton.style.display = DisplayStyle.None;
                }
            }
        }

        bool _enableDown;
        public bool enableDown {
            get => _enableDown;
            set {
                if (_enableDown == value) return;
                _enableDown = value;

                if (value) {
                    downButton.style.display = DisplayStyle.Flex;
                } else {
                    downButton.style.display = DisplayStyle.None;
                }
            }
        }

        bool _enableDelete;
        public bool enableDelete {
            get => _enableDelete;
            set {
                if (_enableDelete == value) return;
                _enableDelete = value;

                if (value) {
                    deleteButton.style.display = DisplayStyle.Flex;
                } else {
                    deleteButton.style.display = DisplayStyle.None;
                }
            }
        }
    }

    internal class InlineWrapper : WrapperBase {

        Label indexLabel;
        VisualElement container;
        public string text {
            set => indexLabel.text = value;
            get => indexLabel.text;
        }

        public override VisualElement contentContainer => container;

        public InlineWrapper() {
            BuildUI();
        }
        protected override void BuildUI() {
            base.BuildUI();

            style.flexDirection = FlexDirection.Row;

            indexLabel = new Label();
            var textEle = indexLabel.Q<TextElement>();
            textEle.style.marginLeft = 0;

            container = new VisualElement() {
                style = {
                    flexGrow = 1
                }
            };

            hierarchy.Add(indexLabel);
            hierarchy.Add(container);
            hierarchy.Add(upButton);
            hierarchy.Add(downButton);
            hierarchy.Add(deleteButton);
        }
    }

    internal abstract class FoldoutWrapperBase : WrapperBase {
        protected FoldoutPro foldout;
        public override VisualElement contentContainer => foldout;
        public string text {
            set => foldout.text = value;
            get => foldout.text;
        }
        protected override void BuildUI() {
            base.BuildUI();
            foldout = new();
            hierarchy.Add(foldout);
            foldout.AddToShoulder(upButton);
            foldout.AddToShoulder(downButton);
            foldout.AddToShoulder(deleteButton);
        }
    }

    internal class FoldoutWrapper : FoldoutWrapperBase {
        public FoldoutWrapper() {
            BuildUI();
        }
        protected override void BuildUI() {
            base.BuildUI();
            foldout.SetListElementStyle();
        }
        /// <summary>
        /// 向标题栏添加控件，比如输入框
        /// </summary>
        public void SetToTitle(VisualElement element) {
            foldout.SetToTitle(element);
        }
    }

    // 与FouldoutWrapper相比：style不同
    internal class FoldoutWrapperPerk : FoldoutWrapper {
        public FoldoutWrapperPerk() {
            BuildUI();
        }
        protected override void BuildUI() {
            base.BuildUI();
            foldout.SetPerkListElementStyle();
        }

    }
}
